<?php

declare(strict_types=1);

namespace Service\CouponService;

use App\Model\BbcModel\Coupon;
use App\Model\BbcModel\CouponGift;
use App\Model\BbcModel\CouponGiftCode;
use App\Model\BbcModel\CouponManual;
use App\Model\BbcModel\CouponStore;
use App\Model\BbcModel\CouponUser;
use App\Model\BbcModel\Goods;
use App\Model\BbcModel\Member;
use App\Model\BbcModel\MnActivity;
use App\Model\BbcModel\MnActivityGoods;
use App\Model\BbcModel\MnStoreGoods;
use App\Model\BbcModel\Mnuser;
use App\Model\BbcModel\Order;
use App\Model\BbcModel\SmsCode;
use Hyperf\DbConnection\Db;
use Service\ActivityService\ActivityService;
use Service\BaseService;
use Service\Code\Normal;
use Service\ConfigureService\ChannelConfigService;
use Service\MemberService\VipService;
use Service\CacheService\CacheProviderService as Cache;
use Service\MessageService\SmsService;
use Service\HelperService\Str;

class CouponService extends BaseService
{
    /**
     * 领券优惠券
     * @param int $coupon_id
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @param string $coupon_code
     * @param int $mid
     * @return array
     */
    public function getCoupon(int $coupon_id, int $cid, int $mnid, int $mn_sid, string $coupon_code, int $mid)
    {
        if (empty($mid)) {
            return Normal::returnCode(Normal::FAIL, '请先登录');
        }

        //todo 活动触发
        //Activity::instance()->updateStatus();
        $isVip = VipService::instance()->checkSingleUserIsBlackVipCard($mid, $mn_sid);

        if (!empty($coupon_id)) {
            $couponInfo = Coupon::instance()->info(['id' => $coupon_id]);
        } else {
            if (empty($coupon_code)) {
                return Normal::returnCode(Normal::FAIL, '缺少优惠券码');
            }
            $manual = CouponManual::instance()->info(['code' => $coupon_code]);
            if (empty($manual)) {
                return Normal::returnCode(Normal::FAIL, '该券不存在，请重新输入');
            }
            $couponInfo = Coupon::instance()->info(['id' => $manual['coupon_id']]);
            if ($couponInfo['coupon_type'] == 2) {
                $receiveResult = $this->receiveGiftCoupon($mid, $couponInfo, $isVip, $cid, $mn_sid);
                if ($receiveResult['code'] != Normal::SUC) {
                    return $receiveResult;
                }
            }
            if ($manual['mid']) {
                return Normal::returnCode(Normal::FAIL, '该券已兑换');
            }
        }
        if (empty($couponInfo)) {
            return Normal::returnCode(Normal::FAIL, '优惠券不存在');
        }
        //新人优惠券领取逻辑已注释
        $currentTime = time();
        if ($couponInfo['rule_type'] == 2 && empty($coupon_code)) {
            return Normal::returnCode(Normal::FAIL, '此优惠券只能通过优惠券码领取');
        }
        if ($couponInfo['is_expiration'] == 2 && $couponInfo['enddate'] < $currentTime) {
            return Normal::returnCode(Normal::FAIL, '优惠券活动已结束');
        }
        if ($couponInfo['is_expiration'] == 2 && $couponInfo['begindate'] > $currentTime && $couponInfo['coupon_type'] != 2) {
            return Normal::returnCode(Normal::FAIL, '优惠券活动还未开始');
        }
        if ($couponInfo['store'] == 2) {
            $store = CouponStore::instance()->info(['mn_sid' => $mn_sid, 'coupon_id' => $couponInfo['id']]);
            if (empty($store)) {
                return Normal::returnCode(Normal::FAIL, '当前店铺没有此优惠券');
            }
        }
        if ($isVip['is_vip'] == 0 && $couponInfo['target_type'] == 3 && $couponInfo['coupon_type'] != 2) {
            return Normal::returnCode(Normal::FAIL, '此优惠券为黑卡会员专属，开卡后立享');
        }
        if ($couponInfo['rule_type'] == 1 && $couponInfo['get'] >= $couponInfo['total']) {
            return Normal::returnCode(Normal::FAIL, '优惠券已被领光');
        }
        $isReceivedCount = CouponUser::instance()->countNum(['mid' => $mid, 'coupon_id' => $couponInfo['id']]);
        if ($isReceivedCount >= $couponInfo['get_num'] && $couponInfo['coupon_type'] != 2) { //非优惠券礼包判断是否已领取完
            return Normal::returnCode(Normal::FAIL, '该优惠券已达领取上限');
        }
        return $this->grantCoupon($couponInfo, $manual, $cid, $mn_sid, $mid);
    }

    /**
     * 领取优惠券礼包
     * @param [type] $mid
     * @param [type] $coupon_info
     * @param [type] $is_vip
     * @param [type] $cid
     */
    public function receiveGiftCoupon($mid, $coupon_info, $is_vip, $cid, $mn_sid)
    {
        if ($coupon_info['status'] == 3) {
            return Normal::returnCode(Normal::FAIL, '优惠券已结束');
        }
        $mobile = Member::instance()->where(['mid' => $mid])->value('account');
        $couponGift = CouponGift::instance()->info(['id' => $coupon_info['coupon_gift_id']]);
        if (empty($couponGift)) {
            return Normal::returnCode(Normal::FAIL, '优惠券礼包不存在');
        }
        if ($couponGift['status'] != 1) {
            return Normal::returnCode(Normal::FAIL, '优惠券礼包已禁用');
        }
        if ($is_vip['is_vip'] == 0 && $coupon_info['target_type'] == 3) {
            return Normal::returnCode(Normal::FAIL, '此优惠券为黑卡会员专属，开卡后立享');
        }
        $userMnMids = Member::instance()->where(['account' => $mobile])->column('mid');
        CouponUser::instance()->startTrans();
        try {
            $lockStatus = CouponUser::instance()->where(['cid' => $cid, 'coupon_id' => $coupon_info['id']])->whereIn('mid', $userMnMids)->lock(true)->column('id');
            if (count($lockStatus) > 0) {
                return Normal::returnCode(Normal::FAIL, '已兑换过该优惠券');
            }
            $couponUser = [
                'coupon_id' => $coupon_info['id'],
                'cid' => $cid,
                'mn_sid' => $mn_sid,
                'mid' => $mid,
                'sid' => getSID(),
                'cd' => time()
            ];
            if ($coupon_info['is_expiration'] == 2) {
                $couponUser['expire_time'] = $coupon_info['enddate'];
            }
            CouponUser::instance()->insert($couponUser);
            CouponUser::instance()->commit();
        } catch (\Exception $e) {
            CouponUser::instance()->rollback();
            return Normal::returnCode(Normal::FAIL, '该券已兑换');
        }
        return Normal::returnCode(Normal::SUC, '兑换成功');
    }

    /**
     * 
     * @param [type] $coupon_info
     * @param [type] $manual
     * @param [type] $cid
     * @param [type] $mn_sid
     * @param [type] $mid
     */
    public function grantCoupon($coupon_info, $manual, $cid, $mn_sid, $mid)
    {
        CouponUser::instance()->startTrans();
        try {
            $newCouponUserData = [
                'coupon_id' => $coupon_info['id'],
                'cid' => $cid,
                'mn_sid' => $mn_sid,
                'mid' => $mid,
                'sid' => getSID(),
                'cd' => time(),
            ];
            if ($coupon_info['is_expiration'] == 2) {
                $newCouponUserData['expire_time'] = $coupon_info['enddate'];
            }
            if ($manual && $coupon_info['coupon_type'] != 2) { //非优惠券礼包
                $newCouponUserData['manual_id'] = $manual['id'];
                CouponManual::instance()->edit(['id' => $manual['id']], [
                    'receive_time' => time(),
                    'mid' => $mid,
                    'status' => 2
                ]);
            }
            if ($coupon_info['coupon_type'] != 2) {
                CouponUser::instance()->insert($newCouponUserData);
            }
            Coupon::instance()->edit(['id' => $coupon_info['id']], ['get' => $coupon_info['get'] + 1]);
            CouponUser::instance()->commit();
        } catch (\Exception $e) {
            CouponUser::instance()->rollback();
            return Normal::returnCode(Normal::FAIL, $e->getMessage());
        }
        return Normal::returnCode(Normal::SUC, '领取成功');
    }

    /**
     * 我的优惠券列表
     * @param int $status
     * @param int $page
     * @param int $limit
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @return array
     */
    public function couponList(int $status, int $page, int $limit, int $cid, int $mnid, int $mn_sid)
    {
        if (empty($mid)) {
            return Normal::returnCode(Normal::FAIL, '请先登录');
        }
        //todo 活动触发
        //Activity::instance()->updateStatus();
        $field = [
            'c.id', 'c.name', 'c.type', 'c.name', 'c.explain', 'c.enddate', 'c.begindate', 'c.addition', 'c.min_amount', 'c.sub_amount', 'c.target_type', 'c.is_expiration', 'cu.receive_time', 'cu.use_time'
        ];

        //判断状态
        if ($status == 1) {
            $order = "cu.cd desc";
        } elseif ($status == 2) {
            $order = "cu.use_time desc";
        } else {
            $order = "cu.expire_time desc";
        }

        $pageInfo = CouponUser::instance()->from(CouponUser::instance()->getTable() . ' as cu')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cu.coupon_id')->where([
                'cu.mid' => $mid,
                'cu.mn_sid' => $mn_sid,
                'cu.status' => $status
            ])->orderByRaw($order)->paginate($limit, $field, 'page', $page, true);
        $list = $pageInfo['data'];
        $formatList = [];
        foreach ($list as $item) {
            $formatList[] = $this->formatCoupon($item);
        }

        $couponUserCounts = CouponUser::instance()->from(CouponUser::instance()->getTable() . ' as cu')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cu.coupon_id')
            ->where([
                'cu.mid' => $mid,
                'cu.mn_sid' => $mn_sid,
            ])->select([
                Db::raw('count(cu.id) counts'),
                'status'
            ])->get()->toArray();

        $couponUserCountsMap = array_column($couponUserCounts, 'counts', 'status');

        return Normal::returnCode(Normal::SUC, '请求成功', [
            'list' => $formatList,
            'num'  => [
                'noUse' => $couponUserCountsMap[1] ?? 0,
                'used' => $couponUserCountsMap[2] ?? 0,
                'expired' => $couponUserCountsMap[3] ?? 0,
            ],
        ]);
    }


    /**
     * 格式化优惠券数据
     * @param [type] $param
     * @return array
     */
    public function formatCoupon(array $param)
    {
        $param['min_amount'] = round($param['min_amount'], 2);
        $param['sub_amount'] = round($param['sub_amount'], 2);
        switch ($param['addition']) {
            default;
            case 1:
                $param['notice'] = "此券与整单促销、商品满减、特价、拼团、秒杀活动不可叠加使用";
                break;
            case 2:
                $param['notice'] = "此券与商品满减、特价、拼团、秒杀活动不可叠加使用";
                break;
            case 3:
                $param['notice'] = "此券与整单促销、特价、拼团、秒杀活动不可叠加使用";
                break;
            case 4:
                $param['notice'] = "此券与特价、拼团、秒杀活动不可叠加使用";
                break;
        }
        if ($param['type'] == 1) {
            $str1 = "全场商品";
        } elseif ($param['type'] == 2) {
            $str1 = "指定商品";
        } elseif ($param['type'] == 3) {
            $str1 = "指定分类";
        } else {
            $str1 = "指定品牌";
        }
        if ($param['min_amount'] > 0) {
            $str2 = "满" . $param['min_amount'] . "使用";
        } else {
            $str2 = "无门槛";
        }
        $param['time'] = "";
        $param['discountNotice'] = $str1 . $str2;
        if ($param['is_expiration'] == 2) {
            $param['time'] = date('Y.m.d', $param['begindate']) . '-' . date('Y.m.d', $param['enddate']);
        }
        return $param;
    }

    /**
     * 优惠券可用商品
     * @param int $coupon_id
     * @param int $page
     * @param int $limit
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @param string $keyword
     * @param int $mid
     * @param int $is_check_vip
     * @return void
     */
    public function couponGoods(int $coupon_id, int $page, int $limit, int $cid, int $mnid, int $mn_sid, string $keyword, int $mid, int $is_check_vip = 1)
    {
        $couponInfoFromMysql = Coupon::instance()->where('id', $coupon_id)->select([
            'id', 'type', 'type_value', 'name', 'is_expiration', 'addition', 'min_amount', 'sub_amount', 'scene', 'store', 'target_type', 'status', 'enddate', 'begindate'
        ])->first();

        if (empty($couponInfoFromMysql)) {
            return Normal::returnCode(Normal::FAIL, '优惠券不存在');
        }
        $couponInfo = $couponInfoFromMysql->toArray();
        $currentTime = time();
        if ($couponInfo['is_expiration'] == 2 && $couponInfo['enddate'] < $currentTime) {
            return Normal::returnCode(Normal::FAIL, '优惠券活动已结束');
        }
        if ($couponInfo['is_expiration'] == 2 && $couponInfo['begindate'] > $currentTime) {
            return Normal::returnCode(Normal::FAIL, '优惠券活动还未开始');
        }
        if ($couponInfo['store'] == 2) {
            $storeCoupon = CouponStore::instance()->info(['mn_sid' => $mn_sid, 'coupon_id' => $couponInfo['id']]);
            if (empty($storeCoupon)) {
                return Normal::returnCode(Normal::FAIL, '当前店铺没有此优惠券');
            }
        }
        $couponInfo = $this->formatCoupon($couponInfo);
        if ($couponInfo['min_amount'] > 0) {
            $couponInfo['content'] = "以下商品可使用满" . round($couponInfo['min_amount'], 2) . "减" . round($couponInfo['sub_amount'], 2) . "的优惠券";
        } else {
            $couponInfo['content'] = "以下商品可使用减" . round($couponInfo['sub_amount'], 2) . "的优惠券";
        }

        $isVip = ['is_vip' => 0, 'expire_time' => 0];
        if ($is_check_vip) {
            if ($mid) {
                $isVip = VipService::instance()->checkSingleUserIsBlackVipCard($mid, $mn_sid);
            }
            if ($isVip['is_vip'] == 0 && $couponInfo['target_type'] == 3) {
                return Normal::returnCode(Normal::FAIL, '此优惠券是黑卡会员专属');
            }
        }

        $where = [
            'g.cid' => $cid,
            'mg.status' => 1,
            'g.df' => 0,
            'g.status' => 1,
            'mg.mn_sid' => $mn_sid
        ];
        $cartWhere = [
            'g.cid' => $cid,
            'g.df' => 0,
            'g.status' => 1,
            'c.mid' => $mid,
            'c.is_send' => 0,
            'c.mn_sid' => $mn_sid
        ];
        if ($couponInfo['type'] == 2) {
            $where[] = ['g.id', explode(',', $couponInfo['type_value'])];
            $cartWhere[] = ['c.goods_id', explode(',', $couponInfo['type_value'])];
        }
        if (!empty($keyword)) {
            //todo 验证一下是否可以添加成功这个条件
            $where[] = ['g.name', 'like', '%' . $keyword . '%'];
        }
        $pageInfo = MnStoreGoods::instance()->from(MnStoreGoods::instance()->getTable() . ' as mg')
            ->join(Goods::instance()->getTable() . ' as g', 'g.id', '=', 'mg.goods_id')
            ->paginate($limit, [
                'g.id', 'g.name', 'g.img', 'g.is_bonded', 'g.fictitious_sale', 'g.num_sale', 'g.price_store', 'g.is_trade', 'g.num_storage', 'mg.num', 'g.tax_rate', 'g.tax_free'
            ], 'page', $page, true);
        $list = $pageInfo['data'];

        //todo 验证一下是否where条件是否有问题
        $specialActivities = MnActivity::instance()->where([
            'mn_sid' => $mn_sid,
            'status' => 1,
            ['startdate', '<', time()],
            ['enddate', '>', time()],
        ])->select(['id', 'type', 'name', 'full', 'drop'])->get()->toArray();

        $level = Mnuser::instance()->where('id', $mn_sid)->value('level');
        $settingPrice = ChannelConfigService::instance()->getPriceSet(['cid' => $cid]);

        //查询是否为特价商品
        $goodsIds = array_column($list, 'id');
        $specialActivityIds = array_column($specialActivities, 'id');
        $specialActivityGoods = MnActivityGoods::instance()->whereIn('mn_activity_id', $specialActivities)
            ->whereIn('goodsId', $goodsIds)->get()->toArray();

        //todo 业务不理解暂时不往下写了 




















        return [];
    }

    /**
     * 优惠券详情
     * @param int $coupon_id
     * @param int $page
     * @param int $limit
     * @param int $mid
     * @return array
     */
    public function couponDetail(int $coupon_id, int $page, int $limit, int $mid)
    {
        //todo 业务不理解暂时不往下写了 

    }

    /**
     * 新人优惠券
     * @param int $cid
     * @param int $mn_sid
     * @param int $page
     * @param int $limit
     * @param int $mid
     * @return array
     */
    public function newPeopleCoupon(int $cid, int $mn_sid, int $page, int $limit, int $mid)
    {
        //todo 活动触发
        //Activity::instance()->updateStatus();
        $whereArray = $this->getCouponWheres($cid, $mn_sid);

        $pageInfo = CouponStore::instance()->from(CouponStore::instance()->getTable() . ' as cs')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cs.coupon_id')
            ->orWhere($whereArray)
            ->orderByRaw('c.cd desc,c.id desc')
            ->paginate($limit, [
                'c.id', 'c.type', 'c.name', 'c.explain', 'c.enddate', 'c.begindate', 'c.addition', 'c.min_amount', 'c.sub_amount', 'c.target_type', 'c.is_expiration', 'c.get,c.total'
            ], 'page', $page, true);

        $list = $pageInfo['data'];

        foreach ($list as $k => $v) {
            //已领取完
            if ($v['get'] >= $v['total']) {
                unset($list[$k]);
            }
        }

        $list = array_values($list);
        if (empty($list)) {
            return Normal::returnCode(Normal::SUC, '该店铺没有新人优惠券', [
                'list' => [],
            ]);
        }

        if (!empty($mid)) {
            $couponIds = array_column($list, 'id');
            $isReceivedCount = CouponStore::instance()->where('mid', $mid)->whereIn('coupon_id', $couponIds)->count();
            if ($isReceivedCount > 0) { //已领取过
                return Normal::returnCode(Normal::SUC, '已领取过新人优惠券', [
                    'list' => [],
                ]);
            }
        }
        foreach ($list as $key => $value) {
            $list[$key] = $this->formatCoupon($value);
        }
        return Normal::returnCode(Normal::SUC, '获取成功', [
            'list' => $list,
        ]);
    }

    /**
     * 黑卡优惠券
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @param int $mid
     * @return array
     */
    public function vipCouponLists(int $cid, int $mnid, int $mn_sid, int $mid)
    {
        //todo 活动触发
        //Activity::instance()->updateStatus();
        $whereArray = $this->getCouponWheres($cid, $mn_sid, ['c.rule_type', 'neq', 2]);

        $totalVipDiscount = Order::instance()->where('mid', $mid)->sum('total_vipDiscount');
        $list = CouponStore::instance()->from(CouponStore::instance()->getTable() . ' as cs')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cs.coupon_id')
            ->orWhere($whereArray)
            ->orderByRaw('c.cd desc,c.id desc')
            ->select([
                'c.id', 'c.type', 'c.name', 'c.explain', 'c.enddate', 'c.begindate', 'c.addition', 'c.min_amount', 'c.sub_amount', 'c.target_type', 'c.is_expiration', 'c.get,c.total'
            ])->get()->toArray();

        if (empty($list)) {
            return Normal::returnCode(Normal::SUC, '请求成功', [
                'list' => $list,
                'total_vipDiscount' => $totalVipDiscount
            ]);
        }

        $couponList = $this->getCouponFormatList($list, $cid, $mnid, $mn_sid, $mid);
        return Normal::returnCode(Normal::SUC, '请求成功', [
            'list' => $couponList,
            'total_vipDiscount' => $totalVipDiscount
        ]);
    }

    /**
     * 一键领取新人优惠券
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @param int $mid
     * @return array
     */
    public function oneGetCoupon(int $cid, int $mnid, int $mn_sid, int $mid)
    {
        //todo 活动触发
        //Activity::instance()->updateStatus();
        if (empty($mid)) {
            return Normal::returnCode(Normal::FAIL, '请先登录');
        }
        $whereArray = $this->getCouponWheres($cid, $mn_sid, ['c.rule_type', 'neq', 2]);
        $list = CouponStore::instance()->from(CouponStore::instance()->getTable() . ' as cs')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cs.coupon_id')
            ->orWhere($whereArray)
            ->orderByRaw('c.cd desc,c.id desc')
            ->select([
                'c.id', 'c.enddate', 'c.is_expiration'
            ])->get()->toArray();
        if (empty($list)) {
            return Normal::returnCode(Normal::FAIL, '该店铺没有新人优惠券');
        }
        $couponIds = array_column($list, 'id');
        $isReceivedCount = CouponStore::instance()->where('mid', $mid)->whereIn('coupon_id', $couponIds)->count();
        if ($isReceivedCount > 0) {
            return Normal::returnCode(Normal::FAIL, '已领取过新人优惠券');
        }

        $newCouponUserData = [];
        $currentTime = time();
        foreach ($list as $key => $value) {
            $newCouponUser = [
                'sid' => getSID(),
                'cid' => $cid,
                'coupon_id' => $value['id'],
                'mn_sid' => $mn_sid,
                'mid' => $mid,
                'receive_time' => $currentTime,
                'cd' => $currentTime,
                'expire_time' => $value['enddate'],
            ];
            if ($value['is_expiration'] == 1) {
                $newCouponUser['expire_time'] = 0;
            }
            $newCouponUserData[] = $newCouponUser;
        }
        $insertResult = CouponUser::instance()->insert($newCouponUserData);

        if ($insertResult === false) {
            return Normal::returnCode(Normal::FAIL, '领取失败');
        }
        return Normal::returnCode(Normal::SUC, '领取成功');
    }

    /**
     * 店铺优惠券列表
     * @param int $cid
     * @param int $mnid
     * @param int $mn_sid
     * @param int $page
     * @param int $limit
     * @param int $mid
     * @return array
     */
    public function storeCouponList(int $cid, int $mnid, int $mn_sid, int $page, int $limit, int $mid)
    {
        //todo 活动触发
        //Activity::instance()->updateStatus();
        $pageInfo = CouponStore::instance()->from(CouponStore::instance()->getTable() . ' as cs')
            ->join(Coupon::instance()->getTable() . ' c', 'c.id', '=', 'cs.coupon_id')
            ->where([
                ['c.cid', 'eq', $cid],
                ['cs.mn_sid', 'in', [0, $mn_sid]],
                ['c.status', 'eq', 2],
                ['c.rule_type', 'in', [0, 1]], //0是新人优惠券
                ['c.scene', 'in', [1, 2]],
            ])->orderByRaw('c.cd desc,c.id desc')
            ->paginate($limit, [
                'c.id', 'c.type', 'c.name', 'c.explain', 'c.enddate', 'c.begindate', 'c.addition', 'c.min_amount', 'c.sub_amount', 'c.target_type', 'c.is_expiration', 'c.get_num', 'c.total', 'c.get'
            ], 'page', $page, true);

        $list = $pageInfo['data'];

        $couponList = $this->getCouponFormatList($list, $cid, $mnid, $mn_sid, $mid);
        return Normal::returnCode(Normal::SUC, '请求成功', [
            'list' => $couponList,
        ]);
    }

    /**
     * 获取领取优惠券短信验证码 
     * @param int $cid
     * @param string $mobile
     * @return array
     */
    public function smsCode(int $cid, string $mobile, int $sms_type, $gift_id = 0)
    {
        if (empty($mobile)) {
            return Normal::returnCode(Normal::FAIL, '缺少手机号');
        }
        $cache_key = "SmsCode_SendSmsCode_{$mobile}_customize";
        $send_times = Cache::getCacheByKey($cache_key) ?? 0;
        if (!empty($send_times) && $send_times >= 3) {
            return Normal::returnCode(Normal::FAIL, '操作频繁');
        }
        $smsConfig = ChannelConfigService::instance()->getConfig(['code' => 'sms_wwtl', 'cid' => $cid]);
        if ($smsConfig['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, '发送失败');
        }

        if ($sms_type == 1) {
            $code = Str::random(6, '0123456789');
            $data = [
                'mobile' => $mobile,
                'code'   => "您的验证码为：" . $code,
                'cd'     => time(),
            ];
            SmsCode::instance()->insert($data);
        } elseif ($sms_type == 2) {
            $code = ''; //todo 获取成功的code
            $sendCouponCodeResult = $this->sendCouponCode($gift_id, $code, $mobile, $cid); //发送券编码
            if ($sendCouponCodeResult['code'] != Normal::SUC) {
                return Normal::returnCode(Normal::SUC, $sendCouponCodeResult['msg']);
            }
        } else {
            return Normal::returnCode(Normal::FAIL, '请求参数错误');
        }

        $sendSmsResult = SmsService::instance()->sendSms([
            'mobile' => $mobile,
            'code' => $code,
            'temp' => 'customize'
        ]);
        if ($sendSmsResult['code'] != Normal::SUC) {
            return Normal::returnCode(Normal::FAIL, $sms_type == 2 ? '领取失败' : $sendSmsResult['msg']);
        }
        $send_times++;
        Cache::setCache($cache_key, $send_times, 60);
        return Normal::returnCode(Normal::SUC, $sms_type == 2 ? $sendCouponCodeResult['msg'] : $sendSmsResult['msg']);
    }

    /**
     * 优惠券礼包状态
     * @param int $cid
     * @param int $bag_id
     * @param int $sms_type
     * @return array
     */
    public function couponBagStatus(int $cid,int $bag_id,int $sms_type):array
    {
        if(empty($cid)){
            return Normal::returnCode(Normal::FAIL.'缺少渠道ID');
        }
        if(empty($bag_id)){
            return Normal::returnCode(Normal::FAIL.'缺少礼包ID');
        }
        $info = CouponGift::instance()->info(['cid'=>$cid,'id'=>$bag_id]);
        if(empty($info)){
            return Normal::returnCode(Normal::FAIL.'优惠券礼包不存在');
        }
        if($info['status'] != 1){
            return Normal::returnCode(Normal::FAIL.'该链接已过期');
        }
        return Normal::returnCode(Normal::SUC.'优惠券礼包正常');
    }


    private function sendCouponCode($gift_id, $code, $mobile, $cid)
    {
        if (empty($gift_id)) {
            return Normal::returnCode(Normal::FAIL, '缺少优惠券礼包ID');
        }
        if (empty($code)) {
            return Normal::returnCode(Normal::FAIL, '请输入验证码');
        }
        $where = [
            ['mobile', '=', $mobile],
            ['status', '=', 0],
            ['cd', '>=', time() - 300],
            '_order_' => 'id desc',
        ];
        $sms_code = SmsCode::instance()->info($where);
        if (empty($sms_code) || $code != $sms_code['code']) {
            return Normal::returnCode(Normal::FAIL, '短信验证码错误');
        }
        $coupon_lists = Db::table('ly_coupon')->where(['cid' => $cid, 'coupon_type' => 2, 'coupon_gift_id' => $gift_id, 'df' => 0])->orderByRaw('status asc,cd desc')->pluck('id'); //当前礼包所有的优惠券
        if (!$coupon_lists) {
            return Normal::returnCode(Normal::FAIL, '没有添加优惠券');
        }
        $use_coupon_id = CouponGiftCode::instance()->where(['mobile' => $mobile])->pluck('coupon_id'); //已发送券ID
        $valid_coupon = [];
        if ($use_coupon_id) {
            foreach ($coupon_lists as $v) {
                if (!in_array($v, $use_coupon_id)) {
                    $valid_coupon[] = $v; // 为领取的优惠券ID
                }
            }
            if (count($valid_coupon) <= 0) { //已全部领取礼包优惠券
                return Normal::returnCode(Normal::FAIL, '亲，你已经领取过该礼包了，快去短信里查收我们发放的优惠券吧');
            }
        }
        if (count($valid_coupon) <= 0) {
            $valid_coupon = $coupon_lists;
        }
        $coupon_lists = CouponManual::instance()->where('coupon_id', 'in', $valid_coupon)->select('coupon_id,code')->get()->toArray();
        if (empty($coupon_lists)) {
            return Normal::returnCode(Normal::FAIL, '没有可领取的优惠券');
        }
        foreach ($coupon_lists as $v) {
            CouponGiftCode::instance()->insert(['cid' => $cid, 'mobile' => $mobile, 'coupon_id' => $v['coupon_id'], 'code' => $v['code'], 'cd' => time(), 'status' => 0]);
        }
        $coupon_code = array_column($coupon_lists, 'code');
        $coupon_code_str = implode(',', $coupon_code);
        SmsCode::instance()->edit(['id' => $sms_code['id']], ['status' => 1]);
        return Normal::returnCode(Normal::SUC, '森免万国购欢迎您的到来，领取的优惠券我们将通过短信方式发送到您的手机，请注意查收', [
            'code' => '优惠券码为：' . $coupon_code_str . '，请到森免万国购商城，到店扫码注册登录后在我的-我的优惠券中兑换使用。'
        ]);
    }



    /**
     * 获取格式化后的couponList
     * @param [type] $cid
     * @param [type] $mn_sid
     * @return array
     */
    private function getCouponFormatList($list, $cid, $mnid, $mn_sid, $mid)
    {
        $couponIds = array_column($list, 'id');
        $couponInfoMap = CouponUser::instance()->whereIn('coupon_id', $couponIds)->where('mid', $mid)->pluck('status', 'coupon_id');

        foreach ($list as $k => $v) {
            $queryGoodsResult = $this->couponGoods($v['id'], 1, 1, $cid, $mnid, $mn_sid, '', $mid, 0);
            if ($queryGoodsResult['code'] != Normal::SUC || count($queryGoodsResult['data']['goodsList']) <= 0) {
                unset($list[$k]);
                continue;
            }
            $list[$k] = $this->formatCoupon($v);
            $couponInfo = $couponInfoMap[$v['id']] ?? [];
            if (empty($couponInfo)) {
                $list[$k]['coupon_status'] = 0;
            } elseif (in_array($couponInfo['status'], [1, 2])) {
                $list[$k]['coupon_status'] = $couponInfo['status'];
            } else {
                $list[$k]['coupon_status'] = 3;
            }
        }
        return array_values($list);
    }

    /**
     * 获取where条件
     * @param [type] $cid
     * @param [type] $mn_sid
     * @return array
     */
    private function getCouponWheres($cid, $mn_sid, $otherCondition = [])
    {
        $time = time();
        $where1 = [
            ['c.cid', 'eq', $cid],
            ['cs.mn_sid', 'eq', 0],
            ['c.target_type', 'eq', 3],
            ['c.status', 'eq', 2],
            ['c.is_expiration', 'eq', 1],
            ['c.rule_type', 'neq', 2],
        ];
        $where2 = [
            ['c.cid', 'eq', $cid],
            ['cs.mn_sid', 'eq', 0],
            ['c.target_type', 'eq', 3],
            ['c.status', 'eq', 2],
            ['c.is_expiration', 'eq', 2],
            ['c.begindate', '<', $time],
            ['c.enddate', '>', $time],
            ['c.rule_type', 'neq', 2],
        ];
        $where3 = [
            ['c.cid', 'eq', $cid],
            ['cs.mn_sid', 'eq', $mn_sid],
            ['c.target_type', 'eq', 3],
            ['c.status', 'eq', 2],
            ['c.is_expiration', 'eq', 2],
            ['c.begindate', '<', $time],
            ['c.enddate', '>', $time],
            ['c.rule_type', 'neq', 2],
        ];
        $where4 = [
            ['c.cid', 'eq', $cid],
            ['cs.mn_sid', 'eq', $mn_sid],
            ['c.target_type', 'eq', 3],
            ['c.status', 'eq', 2],
            ['c.is_expiration', 'eq', 1],
            ['c.rule_type', 'neq', 2],
        ];

        if (!empty($otherCondition)) {
            $where1 = array_merge($where1, $otherCondition);
            $where2 = array_merge($where2, $otherCondition);
            $where3 = array_merge($where3, $otherCondition);
            $where4 = array_merge($where4, $otherCondition);
        }

        return [$where1, $where2, $where3, $where4];
    }

    /**
     * 获取用户在店铺中的可用优惠券
     */
    public function getAbleCoupon($cid, $mn_sid, $otherCondition = []){
        ActivityService::instance()->updateActivityStatusDown();
        $time=time();
        $where=[
            "cu.mid"=>$otherCondition['mid'],
            "cu.mn_sid"=>$mn_sid,
            "cu.status"=>1,
            "c.scene"=>1,
        ];
//        $list=Db::table('ly_coupon_user cu')
//            ->join('ly_coupon c','c.id=cu.coupon_id')
//            ->field('c.id as coupon_id,c.name,c.type,c.type_value,c.name,c.status,c.addition,c.min_amount,c.sub_amount,c.target_type,c.is_expiration,c.begindate,c.enddate,0 as money,0 as is_default')
//            ->where($where)
//            ->where("cu.start_time<$time and ((cu.expire_time>$time and cu.expire_time>0) or cu.expire_time=0)")
//            ->select();
        $query=CouponUser::instance()->from(CouponUser::instance()->getTable() . ' as cu')
            ->join(Coupon::instance()->getTable() . ' as c', 'c.id', '=', 'cu.coupon_id')
            ->where($where)
            ->where('cu.start_time','<',$time);
        $query->where(function ($query_or) use ($time){
            $query_or->where(function ($q) use ($time){
                $q->where('cu.expire_time','>',$time)->where('cu.expire_time','>',0);
            })->orWhere('cu.expire_time','=',0);
        });
       $list= $query->select([
                Db::raw('c.id as coupon_id'),
                Db::raw('0 as money'),
                Db::raw('0 as is_default'),
                'c.name',
                'c.type',
                'c.type_value',
                'c.name',
                'c.status',
                'c.addition',
                'c.min_amount',
                'c.sub_amount',
                'c.target_type',
                'c.is_expiration',
                'c.begindate',
                'c.enddate',
            ])->get()->toArray();

        foreach ($list as $k=> $v){
            $list[$k]=$this->formatCoupon($v);
        }
        return [
            'status' => Normal::SUC,
            'msg'    => '请求成功',
            'data'   => $list
        ];
    }

    /**
     * 优惠券平摊
     */
    public function averageCoupon($param)
    {
        //摊优惠券优惠
        $coupon_pay=$param['coupon_pay'];
        $goods=$param['goods'];
        $useCouponGoods=$param['useCouponGoods'];
        $coupon_fee = (string)$coupon_pay;
        $coupon_goods=[];
        $no_coupon_goods=[];
        foreach ($goods as $v){
            if(!in_array($v['goods_id'],$useCouponGoods)){
                $no_coupon_goods[]=$v;
            }else{
                $coupon_goods[]=$v;
            }
        }
        //数组按支付金额小的排序
        array_multisort(array_column($coupon_goods, 'price'), SORT_ASC, $coupon_goods);
        $price_pay =(string)array_sum(array_column($coupon_goods, 'price'));
        $len = count($coupon_goods);
        $price_coupon = 0; //优惠券优惠金额累加
        for ($i = 0; $i < $len; $i++) {
            if ($i == $len - 1) {
                $pay = $coupon_fee - $price_coupon;
            } else {

                //单个商品占比
                /*$divisor = bcdiv((string)$coupon_goods[$i]['price'], $price_pay, 3);
                $pay = bcmul((string)$coupon_fee, $divisor, 2);*/
                $pay = round($coupon_goods[$i]['price'] / $price_pay * $coupon_fee,2);
                $price_coupon = $price_coupon + $pay;
            }

            $coupon_goods[$i]['price_coupon'] = $pay;
//            $coupon_goods[$i]['price_actual'] = round($coupon_goods[$i]['price_actual']-($pay/$coupon_goods[$i]['num']),2);
            $coupon_goods[$i]['price'] = bcsub((string)$coupon_goods[$i]['price'], (string)$pay, 2);
            if($coupon_goods[$i]['price']<=0){
                $coupon_goods[$i]['price']=0;
            }
        }
        return array_merge($coupon_goods,$no_coupon_goods);
    }



}